﻿#ifndef LK_WINDOWS_UI_CONTROL_
#define LK_WINDOWS_UI_CONTROL_
namespace LK
{
	namespace Windows
	{
		namespace UI
		{
			/**
			@brief 表示一个控件接口*/
			struct IControl :Object
			{
				/**
				@brief 初始化加载控件*/
				static void Initial();
				//委托
#ifdef LK_FUNCTIONAL_ACTION_
				//异步调用
				::LK::Collection::PList<ptr<LK::Functional::IActions> > syncActions;
				//同步调用
				ptr<LK::Functional::IActions>  action;
#endif
				///控件句柄
				HWND hWnd;
			public:
#ifdef LK_FUNCTIONAL_ACTION_
				//按键按下事件
				LK::Functional::PDelegate<void(KeyEventArgs&) > KeyDown;
				//按键弹起事件
				LK::Functional::PDelegate<void(KeyEventArgs&) > KeyUp;
				//按键按下事件
				LK::Functional::PDelegate<void ()> Click;
#endif
				//hMap线程同步
				static Mutex& hMaptc();
				//指针
				static IControl* staticPointer;
				//线程同步
				Mutex tc;
				//不支持复制构造和赋值，调用将抛出PNotSupportException
				IControl(const IControl&) {Throw<PNotSupportException>(); }
				IControl&operator=(const IControl&) { return RThrow<IControl&, PNotSupportException>(); }

				typedef ::LK::Drawing::Point<int> Point;
				typedef ::LK::Drawing::Size<int> Size;
				typedef ::LK::Drawing::Rect<int> Rect;
				//基类通用方法
				IMETHODS(PControl, IControl);
				//析构函数
				virtual ~IControl(){ }///RemovePointerByHandle(hWnd);}
				/**
				@brief 生成空句柄*/
				IControl() :hWnd(NULL){}
				/**
				@brief 使用HANDLE构造，所使用的handle必须非NULL且未添加到映射表，不然将抛出异常*/
				IControl(HWND h) :hWnd(NULL){ if (GetPointerByHandle(h) || !h)Throw<PWindowsException>(L"IControl初始化时指定的句柄为空"); SetHandle(h); }
				/**
				@brief 获取创建窗体的线程id*/
				DWORD GetThreadId()const{ return GetWindowThreadProcessId(hWnd, NULL); }
				/**
				@brief 获取句柄*/
				inline HWND GetHandle()const{ return hWnd; }
				/**
				@brief 设置句柄*/
				void SetHandle(HWND h){ if (h == hWnd)return; hWnd = h; SetWindowLongPtrW(h, GWLP_USERDATA, (LONG_PTR)this); }
				/**
				@brief 获取当前进程实例句柄*/
				static HINSTANCE GetCurrentInstance(){ return GetModuleHandleW(NULL); }
				/**
				@brief 根据句柄获取IControl指针*/
				static IControl* GetPointerByHandle(HWND h){ return (IControl*)GetWindowLongPtrW(h, GWLP_USERDATA); }
				/**
				@brief 将句柄跟IControl指针关联*/
				static void AddPointerByHandle(HWND h, IControl* p){ SetWindowLongPtrW(h, GWLP_USERDATA, (LONG_PTR)p); }

				/**
				@brief 全局消息映射*/
				static LRESULT CALLBACK StaticWndProc(HWND, UINT, WPARAM, LPARAM);
				/**
				@brief 窗体类默认设计*/
				static WNDCLASSEXW& Design();
				/**
				@brief 窗体消息循环*/
				virtual void WndProc(MSG& message);
				/**
				@brief 窗体即将关闭*/
				virtual bool OnCancel(){ return false; }
				/**
				@brief 绘画事件*/
				virtual void OnPaint(){ }
				/**
				@brief 默认消息循环*/
				virtual LRESULT DefWndProc(MSG& message);
				/**
				@brief 构造窗体*/
				virtual HWND Create(
					LPCWSTR text = L"",
					Rect const&position = Rect(0, 0, 0, 0),
					LPCWSTR className = Design().lpszClassName,
					DWORD dwStyle = 0,
					DWORD dwExStyle = 0,
					HWND hParent = NULL,
					HMENU hMenu = NULL);
				/**
				@brief 启动消息循环*/
				void Run();
#ifdef LK_FUNCTIONAL_ACTION_
				/**
				@brief 同步调用*/
				void Invoke(ptr<LK::Functional::IActions>  const& act);
				/**
				@brief 异步调用*/
				void BeginInvoke(ptr<LK::Functional::IActions>  const& act);
#endif
				//属性设置

				/**
				@brief 设置关联文本*/
				virtual void SetText(ptr<String> const&);
				/**
				@brief 获取关联文本*/
				virtual ptr<String> GetText()const;
				/**
				@brief 设置控件最大化时左上角坐标*/
				void SetMaxPosition(Point const& p);
				/**
				@brief 获取控件最大化时左上角坐标*/
				Point GetMaxPosition()const;
				/**
				@brief 设置控件最小化时左上角坐标*/
				void SetMinPosition(Point const& p);
				/**
				@brief 获取控件最小化时左上角坐标*/
				Point GetMinPosition()const;
				/**
				@brief 设置当前控件状态，比如SW_SHOW、SW_HIDE*/
				void SetState(UINT s)const;
				/**
				@brief 获取当前控件状态，比如SW_SHOW、SW_HIDE*/
				UINT GetState()const;
				/**
				@brief 设置显示区域坐标*/
				void SetRect(const Rect&);
				/**
				@brief 获取显示区域坐标*/
				Rect GetRect()const;
				/**
				@brief 设置窗体客户区域大小*/
				void SetClientSize(const Size&);
				/**
				@brief 获取客户区域大小*/
				Size GetClientSize()const;
				/**
				@brief 获取内容字符串长度*/
				index_t GetTextLength()const;
				/**
				@brief 设置字体*/
				void SetFont(HFont const&);
				/**
				@brief 获取字体*/
				HFont GetFont()const;
				/**
				@brief 是否可见*/
				bool IsVisible()const;
				/**
				@brif 添加类型信息*/
				static void AddTypeInfo();
			};
			/**
			@brief 表示控件的代理*/
			class PControl :public ptr<Object>
			{
			public:
				PIMETHODS(PControl, IControl);
				/**
				@brief 获取控件最大化时左上角坐标*/
				Drawing::Point<int> GetMaxPosition()const{ return Check()->GetMaxPosition(); }
				/**
				@brief 设置控件最大化时左上角坐标*/
				void SetMaxPosition(Drawing::Point<int>const& pt)const{ Check()->SetMaxPosition(pt); }
				/**
				@brief 获取控件文本*/
				ptr<String> GetText()const{ return Check()->GetText(); }
				/**
				@brief 设置控件文本*/
				void SetText(const ptr<String>& str){ Check()->SetText(str); }
				/**
				@brief 获取控件位置大小*/
				Drawing::Rect<int> GetRect()const{ return Check()->GetRect(); }
				/**
				@brief 设置控件位置大小*/
				void SetRect(const Drawing::Rect<int>& rect){ Check()->SetRect(rect); }
				/**
				@brief 获取控件字体*/
				HFont GetFont()const{ return Check()->GetFont(); }
				/**
				@brief 设置控件字体*/
				void SetFont(const HFont& f){ Check()->SetFont(f); }
				/**
				@brief 获取控件客户区域大小*/
				Drawing::Size<int> GetClientSize()const{ return Check()->GetClientSize(); }
				/**
				@brief 设置控件客户区域大小*/
				void SetClientSize(const Drawing::Size<int>& rect){ Check()->SetClientSize(rect); }
				/**
				@brief 获取控件句柄*/
				HWND GetHandle()const{ return Check()->GetHandle(); }
				/**
				@brief 获取文本长度*/
				index_t GetTextLength()const{ return Check()->GetTextLength(); }
#ifdef LK_FUNCTIONAL_ACTION_
				/**
				@brief 获取KeyUp事件的引用*/
				LK::Functional::PDelegate<void(KeyEventArgs&)>& GetKeyUpRef(){ return Check()->KeyUp; }
				/**
				@brief 获取KeyDown事件的引用*/
				LK::Functional::PDelegate<void(KeyEventArgs&)>& GetKeyDownRef(){ return Check()->KeyDown; }
				/**
				@brief 获取Click事件的引用*/
				LK::Functional::PDelegate<void()>& GetClickRef(){ return Check()->Click; }
#endif
				/**
				@brief 进入消息循环*/
				void Run(){ Check()->Run(); }
			};
		}
	}
}
#endif
